#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include <time.h>
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include "os_api.h"
#include "debug.h"
#include "hal/gpio.h"

#define _STACK_SIZE		(1024*3)	

static void* _task_stack = NULL;

static OSTaskRef _task_ref = NULL;

static void _task_gpio(void *ptr);

#define GPIO_ISR_PIN_NUM        74
#define GPIO_OUT_PIN_NUM  		12

OS_HISR 	Detect_Hisr;
OSATimerRef DectectTimerRef = NULL;
OSFlagRef  	DetectFlgRef=NULL;
OSATaskRef 	Detect_taskref=NULL;
char 		Detect_StackPtr[1024]={0};

void GPIOIRQHandler (void);
void Detect_TaskEntry(void *param);
void DetectTimerHandler(UINT32 arg);
void Detect_Handler(void);

int main(void)
{
    int ret;

	_task_stack = malloc(_STACK_SIZE);
	ASSERT(_task_stack != NULL);
	
    ret = OSATaskCreate(&_task_ref, _task_stack, _STACK_SIZE, 100, "_task_gpio", _task_gpio, NULL);
    ASSERT(ret == OS_SUCCESS);

	LOG_PRINTF("main exit\n");

	return 0;
}

static int _gpio_set(UINT32 GPIO_NUM, int val)
{
	GPIOReturnCode status = GPIORC_OK;
	
    status = hal_GpioOut(GPIO_NUM, val ? 1 : 0);
	if (status != GPIORC_OK){
		LOG_PRINTF("status: 0x%lx", status);
		return -1;
	}
	
	return 0;
}

static void _task_gpio(void *ptr)
{		
	int value = 0;
	GPIOReturnCode status = GPIORC_OK;
	GPIOConfiguration config;
	
	// 大部分GPIO都可以直接使用(Function 0为GPIO的脚)，，如果遇到部分GPIO不能直接控制,参照下面处理
	// SDK中，GPIO14 和GPIO15 默认被配置成UART3，如果需要作为GPIO使用需要重新配置下，
	// 参照《引脚GPIO说明.xlsx》和《ASR1603 MFPR软件配置.V1.0.pdf》
#if 1	
	//UINT32 tempaddr = 0;
	
	//GPIO 14 15 默认被使能为UART3，作为GPIO使用的话，需要重新修改下对应的寄存器，####
	//tempaddr = hal_GpioMfprAddr(GPIO_ISR_PIN_NUM);
	//*((volatile UINT32 *)tempaddr) = 0xD0B0;	//主要关注最后一个func配置成GPIO即可，Gpio接口也会配置对应属性
	//LOG_PRINTF("GPIO_ISR_PIN_NUM value %lx\n", *((volatile UINT32 *)tempaddr));	
#endif
			
/**********GPIO中断***********/		
	OSATimerCreate(&DectectTimerRef);
	OSAFlagCreate( &DetectFlgRef);  
	Os_Create_HISR(&Detect_Hisr, "Detect_Hisr", Detect_Handler, 2);
	OSATaskCreate(&Detect_taskref, Detect_StackPtr, 1024, 100, "Detect_task", Detect_TaskEntry, NULL);

	config.pinDir = GPIO_IN_PIN;
	config.pinEd = GPIO_TWO_EDGE;
	config.pinPull = GPIO_PULLUP_ENABLE;
	config.isr = GPIOIRQHandler;
	hal_ConfigGpio(GPIO_ISR_PIN_NUM,config);
/**********GPIO中断***********/		


/**********GPIO输出***********/		
	status = hal_GpioSetDir(GPIO_OUT_PIN_NUM, GPIO_OUT_PIN);
	if (status != GPIORC_OK){
		LOG_PRINTF("status: 0x%lx", status);
	}

	while(1) {
		sleep(5);
		value ^= 0x01;
		LOG_PRINTF("%s: value: %d\n", __FUNCTION__, value);	
		if (value){
			_gpio_set(GPIO_OUT_PIN_NUM, 1);
		}else{
			_gpio_set(GPIO_OUT_PIN_NUM, 0);				
		}

    }
/**********GPIO输出***********/	
}


void GPIOIRQHandler (void)
{
	hal_GpioDisableEdgeDet(GPIO_ISR_PIN_NUM, GPIO_TWO_EDGE);

	OS_Activate_HISR(&Detect_Hisr);
}

void Detect_TaskEntry(void *param)
{
	GPIOReturnCode ret;
	UINT32 value;
	OSA_STATUS status;
	UINT32 flag_value = 0;

	while(1)
	{
		LOG_PRINTF("Detect_TaskEntry\r\n");
		status = OSAFlagWait(DetectFlgRef, 0x01, OSA_FLAG_OR_CLEAR, &flag_value, OSA_SUSPEND);
		LOG_PRINTF("OSAFlagWait status %d\r\n", status);
		if(flag_value & 0x01)
		{
			// read the gpio level
			value = hal_GpioIn(GPIO_ISR_PIN_NUM);
			LOG_PRINTF("Detect_TaskEntry value=%d\r\n", value);
		}
	}
}

void DetectTimerHandler(UINT32 arg)
{
	OS_STATUS os_status;

	hal_GpioEnableEdgeDet(GPIO_ISR_PIN_NUM, GPIO_TWO_EDGE);

	os_status = OSAFlagSet(DetectFlgRef, 0x01, OSA_FLAG_OR);
	ASSERT(os_status==OS_SUCCESS);	
}

void Detect_Handler(void)
{
	OS_STATUS status;

	OSATimerStop(DectectTimerRef);
	status = OSATimerStart(DectectTimerRef,
	                         2,
	                         0,
	                         DetectTimerHandler,
	                         0);

	LOG_PRINTF("OSATimerStart status %d\r\n", status);
}
